package com.ylin.coder.core;

import com.ylin.coder.utils.FileUtil;
import com.ylin.coder.utils.Tools;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.util.*;

public class Creater {
	private static DBHelper dbHelper = new DBHelper();
	public Conf conf;
	public Map<String, Object> paraMap = new HashMap<String, Object>(); // 创建数据模型

	/**
	 * 配置数据库
	 */
	public void setDb() {
		dbHelper.setDRIVER(conf.getDbDriver());
		dbHelper.setURL(conf.getDbUrl());
		dbHelper.setUSER_NA(conf.getDbUserNa());
		dbHelper.setPASSWORD(conf.getDbPwd());
		dbHelper.setDB_TYPE(conf.getDbType());
	}

	/**
	 * 代码手动生成到本地
	 * 说明：
	 * 1、tablesMap 中 key 为表名，value 为表前缀，添加后生成的文件名中自动替换掉，比如：表名是 sys_role，最终生成的文件为 Role.java、RoleVo.java ，否则是 SysRole.java
	 * 2、生成代码默认会删除输出路径所有文件，请勿直接将输出路径改为项目路径下
	 * @Auther: masl 2017年5月20日上午11:19:25
	 */
	public void work(Map<String, String> tablesMap) {
		//FileUtil.delFolder(conf.getOutPath()); // 生成代码前,先清空之前生成的代码
		setDb();
		Iterator<String> iter = tablesMap.keySet().iterator();
		while (iter.hasNext()) {
			String tbName = iter.next();
			try {
				String tbPrefix = tablesMap.get(tbName);
				List<String[]> fieldList = dbHelper.getColumns(tbName);
				String pKey = dbHelper.getKeyN(tbName);

				if (fieldList != null && fieldList.size() > 0) {
					List<String[]> newList = new ArrayList<String[]>();
					for (String[] arr : fieldList) {
						//adId,String ad_id,主键,AdId
						String[] newArr = {Tools.littleHump(arr[0]), Tools.sqlType2Java(arr[1]), arr[0], arr[2], Tools.bigHump(arr[0])};
						newList.add(newArr);
					}
					createCodeDetail(tbName, pKey, tbPrefix, newList);
				}
			} catch (Exception e) {
				e.printStackTrace();
				Tools.logger.info("############## 获取表数据列出错 ##############");
			}
		}
	}

	/**
	 * 创建参数集合
	 * @Auther: masl 2017年5月23日上午11:19:59 
	 * @return void
	 */
	public void setParaMap(List<String[]> fieldList, String tableName, String pKey, String className) {
		paraMap.put("fieldList", fieldList);
		paraMap.put("basePackageName", conf.getBasePackageName()); // 包名
		paraMap.put("subPackageName", conf.getSubPackageName()); // 子包名
		paraMap.put("className", className); // 类名
		paraMap.put("subPackAndclassName", StringUtils.isEmpty(conf.getSubPackageName())
				? className
				: (conf.getSubPackageName() + "." + className)); // 类名
		paraMap.put("spotAndSubPack", StringUtils.isEmpty(conf.getSubPackageName())
				? ""
				: "." + className); //.subPackAndclassName

		paraMap.put("classNameLower", className.substring(0, 1).toLowerCase() + className.substring(1)); // 类名(首字母小写)
		paraMap.put("classNameAllUpper", className.toUpperCase()); // 类名(全大写)
		paraMap.put("tableName", tableName); // 表名
		paraMap.put("pKey", new String[] { pKey, Tools.littleHump(pKey) }); // 主键，默认为 id
		paraMap.put("company", conf.getCompany());
		paraMap.put("author", conf.getAuthor());
		paraMap.put("nowDate", new Date()); // 当前日期
	}

	/**
	 * 生成代码
	 * @Auther: masl 2017年5月20日上午10:07:25
	 * @param tableName
	 * @param tbPrefix：表前缀（有值的话可以自动去除表名的前缀）
	 * @param fieldList
	 */
	public void createCodeDetail(String tableName, String pKey, String tbPrefix, List<String[]> fieldList) throws Exception {
		String className = Tools.bigHump(tableName);
		if (Tools.isNotEmpty(tbPrefix)) {
			className = Tools.bigHump(tableName.substring(tbPrefix.length()));
		}
		String subPackageName = conf.getSubPackageName();
		setParaMap(fieldList, tableName, pKey, className);

		FileUtil.delFolder(conf.getOutPath()); // 生成代码前,先清空之前生成的代码

		String basePath = conf.getBasePackageName().replace(".", "/") + "/";

		/* 生成model */
		markFile("modelTemplate.ftl", paraMap, basePath + "model/" + subPackageName + "/" + className + ".java");

		/* 生成vo */
		markFile("voTemplate.ftl", paraMap, basePath + "vo/" + subPackageName + "/" + className + "Vo.java");

		/* 生成mybatis xml */
		markFile("mapperMysqlTemplate.ftl", paraMap, "mybatis/" + subPackageName + "/" + className + "Mapper.xml");

		/* 生成dao */
		markFile("daoTemplate.ftl", paraMap, basePath + "dao/" + subPackageName + "/" + className + "Dao.java");

		/* 生成daoImpl */
		markFile("daoImplTemplate.ftl", paraMap, basePath + "daoImpl/" + subPackageName + "/" + className + "DaoImpl.java");

		/* 生成service */
		markFile("serviceTemplate.ftl", paraMap, basePath + "service/" + subPackageName + "/" + className + "Service.java");

		/* 生成serviceImpl */
		markFile("serviceImplTemplate.ftl", paraMap, basePath + "serviceImpl/" + subPackageName + "/" + className + "ServiceImpl.java");

		/* 生成controller */
		markFile("controllerTemplate.ftl", paraMap, basePath + "controller/" + subPackageName + "/" + className + "Ctl.java");

		/* 生成SQL脚本 */
		//printFile("mysql_SQL_Template.ftl", paraMap, "mysql数据库脚本/" + className.toUpperCase() + ".sql");

		/* 生成jsp页面 */
		markFile("jsp_list_Template.ftl", paraMap, "jsp/" + Tools.littleHump(className) + "/index.jsp");
		markFile("jsp_form_Template.ftl", paraMap, "jsp/" + Tools.littleHump(className) + "/edit.jsp");

		/* 生成说明文档 */
		//printFile("docTemplate.ftl", paraMap, "说明.doc");
	}

	/**
	 * 输出到输出到文件
	 * @param ftlName ftl文件名
	 * @param dataMap 传入的map
	 * @param outFile 输出后的文件全部路径
	 */
	public void markFile(String ftlName, Map<String, Object> dataMap, String outFile) throws Exception {
		try {
			String saveFile = conf.getOutPath() + outFile;
			File file = new File(saveFile);
			if (!file.getParentFile().exists()) { // 判断有没有父路径，就是判断文件整个路径是否存在
				file.getParentFile().mkdirs(); // 不存在就全部创建
			}
			Template template = null;
			Configuration cfg = new Configuration(); // 通过Freemaker的Configuration读取相应的ftl
			cfg.setEncoding(Locale.CHINA, "utf-8");
			String ftlPath = Tools.getClassResources() + conf.getTempleteDirName();
			//模板文件不存在 
			if (!FileUtil.exists(ftlPath + "/" + ftlName)) {
				return;
			}

			cfg.setDirectoryForTemplateLoading(new File(ftlPath)); // 设定去哪里读取相应的ftl模板文件
			template = cfg.getTemplate(ftlName); // 在模板文件目录中找到名称为name的文件
			// 定义模板解释完成之后的输出
			PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(saveFile)));
			// 解释模板
			template.process(dataMap, out);
			Tools.logger.info("生成成功，path = " + saveFile);
		} catch (TemplateException e) {
			e.printStackTrace();
			Tools.logger.error(e.toString());
		} catch (IOException e) {
			Tools.logger.error(e.toString());
		}
	}
}
